/// 1. trait用于定义与其他类型共享的功能，类似于其他语言中的接口
/// 1.1 可以通过trait以抽象的方式定义共享的行为
/// 1.2 可以使用trait bound 指定泛型是任何拥有的特定行为的类型
/// 2. 定义trait
/// 3. 实现trait
/// 4. 默认实现：可以在定义trait的时候提供默认的行为，trait的类型可以使用默认的行为
/// 5. trait作为参数

// 定义一个trait
pub trait GetInformation {
    fn get_name(&self) -> &String;
    fn gey_age(&self) ->u32;
}

trait SchoolName {
    fn get_school_name(&self) -> String {
        String::from("红星小学")
    }
}
// 实现trait
pub struct Student {
    pub name: String,
    pub age: u32,
}
impl GetInformation for Student {
    fn get_name(&self) -> &String {
        &self.name
    }
    fn gey_age(&self) -> u32 {
        self.age
    }
}

pub struct Teacher {
    pub name: String,
    pub age: u32,
    pub subject: String,
}
impl GetInformation for Teacher {
    fn get_name(&self) -> &String {
        &self.name
    }
    fn gey_age(&self) -> u32 {
        self.age
    }
}

// trait作为参数
fn print_information(item: impl GetInformation) {
    println!("name = {}", item.get_name());
    println!("age = {}", item.gey_age());
}

// 默认实现
impl SchoolName for Student {
    fn get_school_name(&self) -> String {
        String::from("光明小学")
    }
}
impl SchoolName for Teacher {}
fn main() {
    let s = Student{name: "张同学".to_string(), age: 12};
    let t = Teacher{name: String::from("李老师"), age: 36, subject: String::from("英语")};
    println!("s.get_name = {}, s.get_age = {}", s.name, s.age);
    println!("t.get_name = {}, t.get_age = {}", t.name, t.age);
    let s1 = s.get_school_name();
    let t1 = t.get_school_name();
    println!("s1 = {}, t1 = {}", s1, t1);

    print_information(s);
    print_information(t);
    println!("Hello, world!");
}
